#include "HardWare_Key.h"
#include "stm32f10x.h"
#include "Common_Time.h"
#include "HardWare_LED.h"

static T_Key_Back S_T_Key_Back;

static T_Key_Back S_T_Key_Sw4_Back;

static T_Key_Back S_T_Key_Sw5_Back;

static T_Key_Back S_T_Key_Sw6_Back;

/**
 * @brief 初始化
 *
 */
void HardWare_Key_sw3_Init(T_Key_Back t_Key_Back)
{
    // 1. 时钟使能
    // gpio, apio
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // gpio组管理
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. 配置 PF10为下拉输入: MODE=00 CNF=10  ODR=0    
    GPIOF->CRH &= ~GPIO_CRH_MODE8;
    GPIOF->CRH |= GPIO_CRH_CNF8_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF8_0;
    // 上下拉,需要通过ODR输出,设置默认值
    GPIOF->ODR |= GPIO_ODR_ODR8;

    // 配置AFIO 配置PF10引脚为外部中断, 开启F组的8号引脚
    // 先设置 =  0
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI8;
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI8_PF;

    // 配置外部中断
    // 开启
    EXTI->IMR |= EXTI_IMR_MR8;
    // 下降沿
    EXTI->FTSR |= EXTI_FTSR_TR8;

    // 5. 配置 NVIC
    // 5.1 配置优先级组 (3-7) 配置3表示4个二进制位全部用于表示抢占优先级, 这个一配置就是全局
    NVIC_SetPriorityGrouping(3);
    // 5.2 配置优先级 参数1:中断号
    NVIC_SetPriority(EXTI9_5_IRQn, 4);
    //  5.3 使能()
    NVIC_EnableIRQ(EXTI9_5_IRQn);

    // 中断回调函数
    S_T_Key_Back = t_Key_Back;
}

/**
 * @brief 初始化sw4
 *
 * @param t_Key_Back 按键回调方法
 */
void HardWare_Key_sw4_Init(T_Key_Back t_Key_Back)
{
    // 时钟使能
    // 引脚
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 模式 输入上拉,
    GPIOF->CRH &= ~GPIO_CRH_MODE9;
    GPIOF->CRH |= GPIO_CRH_CNF9_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF9_0;
    // 添加默认值
    GPIOF->ODR |= GPIO_ODR_ODR9;

    // afio(针脚复用)配置
    // 先置0
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI9;
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI9_PF;

    // 外部中断EXTI配置
    // 开启中断
    EXTI->IMR |= EXTI_IMR_MR9;
    // 下降沿触发
    EXTI->FTSR |= EXTI_FTSR_TR9;

    // nvic
    // 配置全局优先级
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(EXTI9_5_IRQn, 3);
    // 开启使能
    NVIC_EnableIRQ(EXTI9_5_IRQn);

    S_T_Key_Sw4_Back = t_Key_Back;
}

/**
 * @brief 初始化sw5
 *
 * @param t_Key_Back 按键回调方法
 */
void HardWare_Key_sw5_Init(T_Key_Back t_Key_Back)
{
    // 时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 针脚赋值
    GPIOF->CRH |= GPIO_CRH_MODE10;
    GPIOF->CRH |= GPIO_CRH_CNF10_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF10_0;
    // 默认值 = 0
    GPIOF->ODR &= ~GPIO_ODR_ODR10;

    // 针脚复用配置
    // 置0
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI10;
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI10_PF;

    // 设置外部中断
    // 开启中断
    EXTI->IMR |= EXTI_IMR_MR10;
    EXTI->RTSR |= EXTI_RTSR_TR10;

    // nvic 配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(EXTI15_10_IRQn, 4);
    // 开启中断使能
    NVIC_EnableIRQ(EXTI15_10_IRQn);

    S_T_Key_Sw5_Back = t_Key_Back;
}

/**
 * @brief 初始化sw6
 * 
 * @param t_Key_Back 
 */
void HardWare_Key_sw6_Init(T_Key_Back t_Key_Back){

    // 时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 设置模式
    GPIOF->CRH |= GPIO_CRH_MODE11;
    GPIOF->CRH |= GPIO_CRH_CNF11_1;
    GPIOF->CRH |= GPIO_CRH_CNF11_0;
    // 默认值 = 0
    GPIOF->ODR &= ~GPIO_ODR_ODR11;

    // 设置 afoi    
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI11;
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI11_PF;

    // 设置exit
    // 打开中断
    EXTI->IMR |= EXTI_IMR_MR11;
    EXTI->RTSR |= EXTI_RTSR_TR11;

    // nvic配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(EXTI15_10_IRQn,4);
    NVIC_EnableIRQ(EXTI15_10_IRQn);
    S_T_Key_Sw6_Back = t_Key_Back;
}

/**
 * @brief 中断函数
 *
 */
void EXTI9_5_IRQHandler(void)
{

    // 8号针脚被打开
    if (EXTI->PR & EXTI_PR_PR8) {
        // 手动置为8
        EXTI->PR |= EXTI_PR_PR8;

        // 消抖
        time_ms(10);
        if ((GPIOF->IDR & GPIO_IDR_IDR8) == 0) {
            S_T_Key_Back();
        }
    }

    // 9号针脚被打开
    if (EXTI->PR & EXTI_PR_PR9) {
        EXTI->PR &= EXTI_PR_PR9;
        time_ms(10);
        // 不为0,说明还在触发
        if ((EXTI->PR & EXTI_PR_PR9) == 0) {
            S_T_Key_Sw4_Back();
        }
    }
}

/**
 * @brief 中断函数
 *
 */
void EXTI15_10_IRQHandler()
{
    // 被触发
    if (EXTI->PR & EXTI_PR_PR10)
    {
        EXTI->PR |= EXTI_PR_PR10;

        time_ms(10);
        if (EXTI->PR & EXTI_PR_PR10)
        {
            S_T_Key_Sw5_Back();
        }
    } 
    
    if (EXTI->PR & EXTI_PR_PR11)
    {
        EXTI->PR |= EXTI_PR_PR11;
        time_ms(10);
        if (EXTI->PR & EXTI_PR_PR11)
        {
            S_T_Key_Sw6_Back();
        }
        
    }
    
}